import json
from django.http import JsonResponse
from django.views.generic import View
from ..serializers.authorListSerializer import AuthorListQuerySerializer, AuthorListSerializer
from ..utils.literUtils import handle_serializer_error, emptyValue
from django.db.models import Q
from django.core.paginator import Paginator
from utils.encryptionAndDecryptionUtil import get_useraccount_from_request
from ..serializers.authorInfoSerializer import AuthorCreateSerializer, AuthorInfoSerializer
from ..models.Author import Author
from datetime import datetime
import traceback
import copy
from control.models.User import User
from ..models.Keyword import Keyword
from ..models.GlobalTables import KeywordType
from ..models.Institution import Institution
from ..models.Department import Department
from ..serializers.keywordInfoSerializer import TagCreateSerializer
from ..models.GlobalTables import InstitutionType, DepartmentType
from ..serializers.instInfoSerializer import InstCreateSerializer
from ..serializers.departInfoSerializer import DepartCreateSerializer

class AuthorView(View):
    def get(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            data = request.GET
            query_list_serializer = AuthorListQuerySerializer(data=data)
            data_valid = query_list_serializer.is_valid()
            if not data_valid:
                res["code"] = 400
                res["message"] = "参数错误：" + \
                    handle_serializer_error(
                        errors=query_list_serializer.errors)
                return JsonResponse(res)
            data = query_list_serializer.validated_data
            authors = Author.objects.all().order_by('-create_date')
            query = Q()
            if "name" in data and data["name"] != "":
                query &= Q(name__icontains=data["name"])
            if "zh_name" in data and data["zh_name"] != "":
                query &= Q(zh_name__icontains=data["zh_name"])
            if 'orcid' in data and data['orcid'] != "":
                query &= Q(orcid__icontains=data["orcid"])
            if 'email' in data and data['email'] != "":
                query &= Q(email__icontains=data["email"])
            if 'address' in data and data['address'] != "":
                query &= Q(address__icontains=data["address"])
            if 'country' in data and data['country'] != "":
                query &= Q(country__icontains=data["country"])
            if 'city' in data and data['city'] != "":
                query &= Q(city__icontains=data["city"])
            if 'phone' in data and data['phone'] != "":
                query &= Q(phone__icontains=data["phone"])
            if 'education_degree' in data and data['education_degree'] != "":
                query &= Q(education_degree__icontains=data["education_degree"])
            if 'research_field' in data and data['research_field'] != "":
                query &= Q(research_field__icontains=data["research_field"])
            if 'cited_count' in data and data['cited_count'] != "":
                query &= Q(cited_count__icontains=data["cited_count"])
            if 'homepage' in data and data['homepage'] != "":
                query &= Q(homepage__icontains=data["homepage"])
            if 'description' in data and data['description'] != "":
                query &= Q(description__icontains=data["description"])

            order_list_combined = []
            prop_list = data.get('sort_prop', '').split(
                ',') if data.get('sort_prop') else []
            order_list = data.get('sort_order', '').split(
                ',') if data.get('sort_order') else []
            if len(prop_list) != len(order_list):
                res["code"] = 400
                res["message"] = "排序参数错误"
                return JsonResponse(res)
            for i in range(len(prop_list)):
                for prop, order in zip(prop_list, order_list):
                    if order.lower() == 'ascending':
                        order_list_combined.append(prop)
                    elif order.lower() == 'descending':
                        order_list_combined.append(f'-{prop}')
            if len(query) != 0:
                authors = authors.filter(query)

            if 'tag' in data and data['tag'] != "":
                tl = data['tag'].split(";")
                ktp = KeywordType.objects.filter(name="Tag")[0]
                tag_all = Keyword.objects.filter(kt=ktp)
                for tn in tl:
                    tt = tn.strip()
                    ta = tag_all.filter(Q(k__icontains=tt) | Q(v__icontains=tt))
                    tmp_authors = set()
                    for aaa in authors.filter(tag__in=ta).all():
                        tmp_authors.add(aaa.uuid)
                    authors = authors.filter(uuid__in=tmp_authors)
            if 'institutions' in data and data['institutions'] != "":
                il = data['institutions'].split(";")
                for i in il:
                    ii = i.strip()
                    ti = Institution.objects.filter(Q(name__icontains=ii) | Q(zh_name__icontains=ii))
                    tmp_authors = set()
                    for aaa in authors.filter(institutions__in=ti).all():
                        tmp_authors.add(aaa.uuid)
                    authors = authors.filter(uuid__in=tmp_authors)
            if 'departments' in data and data['departments'] != "":
                dl = data['departments'].split(";")
                for dn in dl:
                    dd = dn.strip()
                    td= Department.objects.filter(Q(name__icontains=dd) | Q(zh_name__icontains=dd))
                    tmp_authors = set()
                    for aaa in authors.filter(departments__in=td).all():
                        tmp_authors.add(aaa.uuid)
                    authors = authors.filter(uuid__in=tmp_authors)


            if len(order_list_combined) != 0:
                authors = authors.order_by(*order_list_combined)
            total_count = authors.count()
            res_data = {}
            if "page_size" in data:
                page_size = data["page_size"]
                current_page = data["current_page"]
                paginator = Paginator(authors, page_size)
                if current_page > paginator.num_pages:
                    current_page = paginator.num_pages
                page_obj = paginator.get_page(current_page)
                res_data["current_page"] = current_page
                res_data["page_size"] = page_size
                res_data["total_count"] = total_count
                author_list_serializer = AuthorListSerializer(
                    page_obj, many=True)
                res_data["objects"] = author_list_serializer.data
                res["code"] = 200
                res["message"] = "查询成功"
                res["data"] = res_data
                return JsonResponse(res)
            res_data["total_count"] = total_count
            author_list_serializer = AuthorListSerializer(
                authors, many=True)
            res_data["objects"] = author_list_serializer.data
            res["code"] = 200
            res["message"] = "查询成功"
            res["data"] = res_data
            return JsonResponse(res)
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def post(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            u = User.objects.filter(user_account=user_name)[0]
            data = json.loads(request.body)
            # print(data)
            
            tag_id_list = []
            for tag in data['tag']:
                if 'uuid' in tag:
                    tag_id_list.append(tag['uuid'])
                else:
                    tag_add_serializer = TagCreateSerializer(data=tag)
                    tag_data_valid = tag_add_serializer.is_valid()
                    if not tag_data_valid:
                        print(tag_add_serializer.errors)
                        tag_serial_errors = handle_serializer_error(
                            errors=tag_add_serializer.errors)
                        res["code"] = 400
                        res["message"] = "参数错误：\n" + tag_serial_errors
                        return JsonResponse(res)
                    tag_data = tag_add_serializer.validated_data
                    tag_data["creator"] = u
                    tag_data["last_editor"] = u
                    tag_data['kt'] = KeywordType.objects.filter(name='Tag')[0]
                    t = Keyword.objects.create(**tag_data)
                    tag_id_list.append(t.uuid)
                    
            data['tag'] = tag_id_list
            
            inst_infos = []
            for inst in data["institutions"]:
                inst_infos.append(copy.deepcopy(inst))
                if not isinstance(inst.get("departments"), list):
                    inst["departments"] = []
            
            for dep in data["departments"]:
                for i,inst in enumerate(inst_infos):
                # for inst in data["institutions"]:
                    if dep["institution"] == inst:
                        data["institutions"][i]["departments"].append(dep)
                        
            institution_id_list = []
            department_id_list = []
            for inst in data["institutions"]:
                dep_data_list = inst.pop('departments', [])
                i_uuid = None
                if "uuid" in inst:
                    i_uuid = inst["uuid"]
                    institution_id_list.append(i_uuid)
                else:
                    inst['founded_date'] = None if emptyValue(inst['founded_date']) else datetime.fromisoformat(inst['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
                    inst['inst_type'] = InstitutionType.objects.filter(name='unknown')[0].uuid if emptyValue(inst['inst_type']) else inst['inst_type']
                    inst_add_serializer = InstCreateSerializer(data=inst)
                    inst_data_valid = inst_add_serializer.is_valid()
                    if not inst_data_valid:
                        print(inst_add_serializer.errors)
                        inst_serial_errors = handle_serializer_error(
                            errors=inst_add_serializer.errors)
                        res["code"] = 400
                        res["message"] = "参数错误：\n" + inst_serial_errors
                        return JsonResponse(res)
                    inst = inst_add_serializer.validated_data
                    inst["creator"] = u
                    inst["last_editor"] = u
                    i = inst_add_serializer.save()
                    i_uuid = i.uuid
                    institution_id_list.append(i_uuid)
                
                for dep in dep_data_list:
                    if "uuid" in dep:
                        department_id_list.append(dep['uuid'])
                    else:
                        dep['founded_date'] = None if emptyValue(dep['founded_date']) else datetime.fromisoformat(dep['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
                        dep['dep_type'] = DepartmentType.objects.filter(name='unknown')[0].uuid if emptyValue(dep['dep_type']) else dep['dep_type']
                        dep["institution"] = i_uuid
                        depart_add_serializer = DepartCreateSerializer(data=dep)
                        depart_data_valid = depart_add_serializer.is_valid()
                        if not depart_data_valid:
                            print(depart_add_serializer.errors)
                            depart_serial_errors = handle_serializer_error(
                                errors=depart_add_serializer.errors)
                            res["code"] = 400
                            res["message"] = "参数错误：\n" + depart_serial_errors
                            return JsonResponse(res)
                        depart_data = depart_add_serializer.validated_data
                        depart_data["creator"] = u
                        depart_data["last_editor"] = u
                        d = depart_add_serializer.save()
                        department_id_list.append(d.uuid)
                        
            data['institutions'] = institution_id_list
            data['departments'] = department_id_list
            
            add_serializer = AuthorCreateSerializer(data=data)
            data_valid = add_serializer.is_valid()
            if not data_valid:
                print(add_serializer.errors)
                serial_errors = handle_serializer_error(
                    errors=add_serializer.errors)
                res["code"] = 400
                res["message"] = "参数错误：\n" + serial_errors
                return JsonResponse(res)
            data = add_serializer.validated_data
            data["creator"] = u
            data["last_editor"] = u

            add_serializer.save()
            res["code"] = 200
            res["message"] = "新建成功"
            res["data"] = None
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    
class AuthorInfoView(View):
    def get(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            author = Author.objects.get(uuid=id)
            author = AuthorInfoSerializer(author).data
            
            for inst in author["institutions"]:
                dep_data = inst.pop("departments", [])
                for dep in author["departments"]:
                    if dep["institution"] == inst:
                        dep["institution"] = inst
                inst["departments"] = dep_data
            
            res["code"] = 200
            res["message"] = "查询成功"
            res["data"] = author
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def delete(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            a = Author.objects.get(uuid=id)
            if a is None:
                res["code"] = 400
                res["message"] = "该条目不存在"
                return JsonResponse(res)
            
            if a.cited_count > 0:
                res["code"] = 400
                res["message"] = "删除失败：仍有其他文献引用该作者"
                return JsonResponse(res)
            
            if len(a.literature_set.all()) > 0:
                res["code"] = 400
                res["message"] = "删除失败：该作者仍有署名文献在库"
                return JsonResponse(res)
            
            if len(a.book_set.all()) > 0:
                res["code"] = 400
                res["message"] = "删除失败：该作者仍有署名书籍在库"
                return JsonResponse(res)
            
            a.tag.clear()
            a.institutions.clear()
            a.departments.clear()
            a.delete()
            res["code"] = 200
            res["message"] = "删除成功"
            res["data"] = None
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def put(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            u = User.objects.filter(user_account=user_name)[0]
            data = json.loads(request.body)
            
            tag_id_list = []
            for tag in data['tag']:
                if 'uuid' in tag:
                    tag_id_list.append(tag['uuid'])
                else:
                    tag_add_serializer = TagCreateSerializer(data=tag)
                    tag_data_valid = tag_add_serializer.is_valid()
                    if not tag_data_valid:
                        print(tag_add_serializer.errors)
                        tag_serial_errors = handle_serializer_error(
                            errors=tag_add_serializer.errors)
                        res["code"] = 400
                        res["message"] = "参数错误：\n" + tag_serial_errors
                        return JsonResponse(res)
                    tag_data = tag_add_serializer.validated_data
                    tag_data["creator"] = u
                    tag_data["last_editor"] = u
                    tag_data['kt'] = KeywordType.objects.filter(name='Tag')[0]
                    t = Keyword.objects.create(**tag_data)
                    tag_id_list.append(t.uuid)
                    
            data['tag'] = tag_id_list
            
            inst_infos = []
            for inst in data["institutions"]:
                inst_infos.append(copy.deepcopy(inst))
                if not isinstance(inst.get("departments"), list):
                    inst["departments"] = []
            
            for dep in data["departments"]:
                for i,inst in enumerate(inst_infos):
                # for inst in data["institutions"]:
                    if dep["institution"] == inst:
                        data["institutions"][i]["departments"].append(dep)
                        
            # print(data)
            institution_id_list = []
            department_id_list = []
            for inst in data["institutions"]:
                dep_data_list = inst.pop('departments', [])
                i_uuid = None
                if "uuid" in inst:
                    i_uuid = inst["uuid"]
                    institution_id_list.append(i_uuid)
                else:
                    inst['founded_date'] = None if emptyValue(inst['founded_date']) else datetime.fromisoformat(inst['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
                    inst['inst_type'] = InstitutionType.objects.filter(name='unknown')[0].uuid if emptyValue(inst['inst_type']) else inst['inst_type']
                    inst_add_serializer = InstCreateSerializer(data=inst)
                    inst_data_valid = inst_add_serializer.is_valid()
                    if not inst_data_valid:
                        print(inst_add_serializer.errors)
                        inst_serial_errors = handle_serializer_error(
                            errors=inst_add_serializer.errors)
                        res["code"] = 400
                        res["message"] = "参数错误：\n" + inst_serial_errors
                        return JsonResponse(res)
                    inst = inst_add_serializer.validated_data
                    inst["creator"] = u
                    inst["last_editor"] = u
                    i = inst_add_serializer.save()
                    i_uuid = i.uuid
                    institution_id_list.append(i_uuid)
                
                for dep in dep_data_list:
                    if "uuid" in dep:
                        department_id_list.append(dep['uuid'])
                    else:
                        dep['founded_date'] = None if emptyValue(dep['founded_date']) else datetime.fromisoformat(dep['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
                        dep['dep_type'] = DepartmentType.objects.filter(name='unknown')[0].uuid if emptyValue(dep['dep_type']) else dep['dep_type']
                        dep["institution"] = i_uuid
                        depart_add_serializer = DepartCreateSerializer(data=dep)
                        depart_data_valid = depart_add_serializer.is_valid()
                        if not depart_data_valid:
                            print(depart_add_serializer.errors)
                            depart_serial_errors = handle_serializer_error(
                                errors=depart_add_serializer.errors)
                            res["code"] = 400
                            res["message"] = "参数错误：\n" + depart_serial_errors
                            return JsonResponse(res)
                        depart_data = depart_add_serializer.validated_data
                        depart_data["creator"] = u
                        depart_data["last_editor"] = u
                        d = depart_add_serializer.save()
                        department_id_list.append(d.uuid)
                        
            data['institutions'] = institution_id_list
            data['departments'] = department_id_list
            
            author = Author.objects.get(uuid=id)
            modify_serializer = AuthorCreateSerializer(instance=author,data=data)
            data_valid = modify_serializer.is_valid()
            if not data_valid:
                res["code"] = 400
                res["message"] = "参数错误：" + \
                    handle_serializer_error(
                        errors=modify_serializer.errors)
                return JsonResponse(res)
            data = modify_serializer.validated_data
            data["last_editor"] = u
            
            modify_serializer.save()
            res["code"] = 200
            res["message"] = "编辑成功"
            res["data"] = None
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
            print(e)
        return JsonResponse(res)